/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.bef.engine.core.be;

import com.inspur.edp.bef.api.be.IBENodeEntity;
import com.inspur.edp.bef.bizentity.GspBizEntityObject;
import com.inspur.edp.bef.bizentity.GspBusinessEntity;
import com.inspur.edp.bef.bizentity.operation.internalmgraction.TccSettingElement;
import com.inspur.edp.bef.core.be.BENodeEntity;
import com.inspur.edp.bef.core.be.builtinimpls.BeEntityCacheInfo;
import com.inspur.edp.bef.core.tcc.builtinimpls.BefTccHandlerAssembler;
import com.inspur.edp.bef.engine.common.GspBizEntityUtil;
import com.inspur.edp.bef.engine.core.BefEngineInfoCache;
import com.inspur.edp.bef.engine.core.dtm.AfterCreateDtm;
import com.inspur.edp.bef.engine.core.dtm.AfterLoadingDtm;
import com.inspur.edp.bef.engine.core.dtm.AfterModifyDtm;
import com.inspur.edp.bef.engine.core.dtm.BeforeSaveDtm;
import com.inspur.edp.bef.engine.core.dtm.OnCancelDtm;
import com.inspur.edp.bef.engine.core.val.AfterModifyVal;
import com.inspur.edp.bef.engine.core.val.AfterSaveVal;
import com.inspur.edp.bef.engine.core.val.BeforeSaveVal;
import com.inspur.edp.bef.engine.entity.EngineChildAccessor;
import com.inspur.edp.bef.engine.entity.EngineChildData;
import com.inspur.edp.cef.entity.entity.IEntityData;
import com.inspur.edp.cef.spi.determination.IEntityRTDtmAssembler;
import com.inspur.edp.cef.spi.entity.resourceInfo.builinImpls.CefEntityResInfoImpl;
import com.inspur.edp.cef.spi.entityaction.CefDataTypeAction;
import com.inspur.edp.cef.spi.validation.IEntityRTValidationAssembler;
import com.inspur.edp.das.commonmodel.IGspCommonObject;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import org.springframework.util.StringUtils;

public class EngineChildEntity extends BENodeEntity {

  private GspBusinessEntity gspBusinessEntity;
  private GspMetadata metadata;
  private final IGspCommonObject node;
  private final  CefEntityResInfoImpl parentEntityResInfo;

  public EngineChildEntity(GspBusinessEntity gspBusinessEntity, IGspCommonObject beNode, String dataId, CefEntityResInfoImpl parentEntityResInfo) {
    super(dataId);
    this.gspBusinessEntity = gspBusinessEntity;
    this.node = beNode;
    this.parentEntityResInfo = parentEntityResInfo;
  }

  public EngineChildEntity(GspBusinessEntity gspBusinessEntity, IGspCommonObject beNode, String dataId, CefEntityResInfoImpl parentEntityResInfo, GspMetadata metadata) {
    super(dataId);
    this.gspBusinessEntity = gspBusinessEntity;
    this.node = beNode;
    this.parentEntityResInfo = parentEntityResInfo;
    this.metadata = metadata;
  }

  @Override
  protected int getVersion() {
    return 1;
  }

  @Override
  protected IEntityData innerCreateEntityData(String id) {
    EngineChildData data = new EngineChildData(node, getEntityResInfo());
    data.setID(id);
    GspBizEntityUtil.initBeDataValue(node, data, null, getEntityResInfo());
    return data;
  }

  @Override
  public IEntityData innerCreateChildEntityData(String childCode, String id) {
    IGspCommonObject childNode = GspBizEntityUtil.findNode(this.node, childCode);
    EngineChildData data = new EngineChildData(childNode,
        (CefEntityResInfoImpl) getEntityResInfo().getChildEntityResInfo(childNode.getCode()));
    data.setID(id);
    GspBizEntityUtil.initBeDataValue(childNode, data, null, getEntityResInfo());
    return data;
  }

  @Override
  public IEntityData innerCreateChildAccessor(String childCode, IEntityData data) {
    IGspCommonObject childNode = GspBizEntityUtil.findNode(this.node, childCode);
    return new EngineChildAccessor(childNode, data,
        (CefEntityResInfoImpl) getEntityResInfo().getChildEntityResInfo(childNode.getCode()));
  }

  @Override
  protected IBENodeEntity innerGetChildBEEntity(String childCode, String id) {
    EngineChildEntity entity = new EngineChildEntity(gspBusinessEntity, GspBizEntityUtil.findNode(node, childCode)
        , id,getEntityResInfo(),metadata);
    entity.setContext(createChildEntityContext(childCode, id));
    entity.setParent(this);
    return entity;
  }
//
//  @Override public void assignDefaultValue(com.inspur.edp.cef.entity.entity.IEntityData data){
//    GspBizEntityUtil.assignDefaultValue(node, data);
//  }

  @Override
  protected IEntityRTDtmAssembler createAfterModifyDtmAssembler(){
    return new AfterModifyDtm((GspBizEntityObject)node);
  }

  @Override
  protected IEntityRTDtmAssembler createBeforeSaveDtmAssembler(){
    return new BeforeSaveDtm((GspBizEntityObject)node);
  }

  @Override protected com.inspur.edp.cef.spi.determination.IEntityRTDtmAssembler createRetrieveDefaultDtmAssembler(){
    return new AfterCreateDtm((GspBizEntityObject)node);
  }

  @Override
  public IEntityRTDtmAssembler createOnCancelDtmAssembler() {
    return new OnCancelDtm((GspBizEntityObject) node);
  }

  @Override
  public IEntityRTDtmAssembler createAfterLoadingDtmAssembler(){
    return new AfterLoadingDtm((GspBizEntityObject) node);
  }

  @Override
  protected IEntityRTValidationAssembler createAfterModifyValidationAssembler(){
    return new AfterModifyVal(gspBusinessEntity, (GspBizEntityObject)node);
  }

  @Override
  protected IEntityRTValidationAssembler createBeforeSaveValidationAssembler(){
    return new BeforeSaveVal(gspBusinessEntity, (GspBizEntityObject)node);
  }

  @Override
  protected IEntityRTValidationAssembler createAfterSaveValAssembler() {
    return new AfterSaveVal(gspBusinessEntity, (GspBizEntityObject) node);
  }

  @Override
  public  Object executeBizAction(String actionCode, Object... pars) {
    CefDataTypeAction action = GspBizEntityUtil
        .instantiateBizAction((GspBizEntityObject)node, actionCode, getBEContext(), pars);
    return execute(action);
  }

  @Override
  public CefEntityResInfoImpl getEntityResInfo() {
    return (CefEntityResInfoImpl) parentEntityResInfo.getChildEntityResInfo(node.getCode());
  }

  @Override
  protected BeEntityCacheInfo getBeEntityCacheInfo() {
    if(metadata!=null && metadata.getProperties()!=null && metadata.getProperties().getCacheVersion()!=null && !"".equals(metadata.getProperties().getCacheVersion())) {
      return BefEngineInfoCache.getBefEngineInfo(gspBusinessEntity.getID(), metadata.getProperties().getCacheVersion()).getBeEntityCacheInfo(node.getID());
    }else {
      return BefEngineInfoCache.getBefEngineInfo(gspBusinessEntity.getID()).getBeEntityCacheInfo(node.getID());
    }
  }

  @Override
  protected BefTccHandlerAssembler createTccAssembler() {
    BefTccHandlerAssembler rez = super.createTccAssembler();
    if (gspBusinessEntity.isTccSupported() && (!gspBusinessEntity.isAutoCancel()
        || !gspBusinessEntity.isAutoComplete())
        && ((GspBizEntityObject) node).getTccSettings() != null) {
      for (TccSettingElement tccSetting : ((GspBizEntityObject) node).getTccSettings()) {
        if (tccSetting.getTccAction() == null || StringUtils
            .isEmpty(tccSetting.getTccAction().getComponentId())) {
          GspBizEntityUtil.throwNoTccComp((GspBizEntityObject) node, tccSetting);
        }
        rez.addHandler(tccSetting.getCode(), tccSetting.getTccAction().getComponentId());
      }
    }
    return rez;
  }
}
